package com.bwie.service.Impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bwie.pojo.Menu;
import com.bwie.utils.KaptchaUtils;
import com.bwie.utils.MD5Utils;
import com.bwie.utils.MobileMessageUtil;
import com.bwie.utils.R;
import com.bwie.vo.LoginVo;
import com.bwie.vo.PageInfoVo;
import com.bwie.vo.PhoneLoginVo;
import com.bwie.vo.SendVo;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.pojo.User;
import com.bwie.mapper.UserMapper;
import com.bwie.service.UserService;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;

@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{
    @Autowired
    private UserMapper  userMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private HttpServletResponse response;
    @Override
    public R login(LoginVo loginVo) {
        User user1 = userMapper.selectOne(
                new QueryWrapper<User>().lambda().eq(User::getUserName,loginVo .getUserName())
        );
        if(ObjectUtils.isEmpty(user1)){
            return R.ERROR(500,"用户不存在");
        }
        String encrypt = MD5Utils.encrypt(loginVo.getUserPass());
        System.out.println("加密的密码是:"+encrypt);
        if(!MD5Utils.encrypt(loginVo.getUserPass()).equalsIgnoreCase(user1.getUserPass())){
            return R.ERROR(500,"密码错误");
        }
        String token = Jwts.builder().signWith(SignatureAlgorithm.HS256, "123456")
                .claim("userId", user1.getUserId())
                .claim("userName",user1.getUserName()).compact();
        String tokenKey = "token-"+user1.getUserId();
        redisTemplate.opsForValue().set(tokenKey,token,20, TimeUnit.MINUTES);
        user1.setToken(token);
        return R.OK(user1);
    }

    @Override
    public R treeList(Integer userId) {
        List<Menu> menus = userMapper.treeList(userId);
        List<Tree<String>> build = TreeUtil.build(menus, "0", (menu, treeNode) -> {
            treeNode.setName(menu.getMenuName());
            treeNode.setParentId(menu.getMenuPid().toString());
            treeNode.setId(menu.getMenuId().toString());
            treeNode.putExtra("path", menu.getMenuPath());
        });
        return R.OK(build);
    }

    @Override
    public R userList(PageInfoVo pageInfoVo) {
        Page<User> userPage = new Page<>(pageInfoVo.getPageNum(),pageInfoVo.getPageSize());
        Page<User> userPage1 = userMapper.selectPage(userPage, null);
        return R.OK(userPage1);
    }

    @Override
    public R getImageCode() {
        String ImagesCode = RandomUtil.randomNumbers(4);
        KaptchaUtils.generateCaptcha(response,ImagesCode);
        String imageCodeKey = "imagesCode";
        redisTemplate.opsForValue().set(imageCodeKey,ImagesCode,2,TimeUnit.MINUTES);
        return R.OK();
    }

    @Override
    public R sendPhoneCode(SendVo sendVo) {
        String phoneCodeKey = "send-phoneCode";
        Boolean b = redisTemplate.hasKey(phoneCodeKey);
        if(b){
            return R.ERROR(500,"不能频繁发送手机验证码");
        }
        //判断图片验证码
        String imageCodeKey = "imagesCode";
        String redisImagesCode = redisTemplate.opsForValue().get(imageCodeKey);
        if(StringUtils.isEmpty(redisImagesCode)){
            return R.ERROR(500,"图片验证码已过期");
        }
        if(!redisImagesCode.equalsIgnoreCase(sendVo.getImageCode())){
            return R.ERROR(500,"图片验证码错误");
        }
        //判断手机号是否存在
        User user = userMapper.selectOne(
                new QueryWrapper<User>().lambda().eq(User::getUserMobile, sendVo.getUserMobile())
        );
        if(ObjectUtils.isEmpty(user)){
            return R.ERROR(500,"手机号未注册");
        }
        if(!user.getUserMobile().equalsIgnoreCase(sendVo.getUserMobile())){
            return R.ERROR(500,"手机号错误");
        }
        //发送手机号验证码
        String phoneCode = RandomUtil.randomNumbers(4);
        MobileMessageUtil.sendMobileMessage(user.getUserMobile(),phoneCode);
        //5分钟只能发送一次
        String CodeKey ="phoneCode";
        redisTemplate.opsForValue().set(CodeKey,phoneCode,5,TimeUnit.MINUTES);
        //1分钟只能发送一次验证码
        redisTemplate.opsForValue().set(phoneCodeKey,phoneCode,1,TimeUnit.MINUTES);
        return R.OK();
    }

    @Override
    public R PhoneLogin(PhoneLoginVo phoneLoginVo) {
        //查找手机号是否存在
        User user = userMapper.selectOne(
                new QueryWrapper<User>().lambda().eq(User::getUserMobile, phoneLoginVo.getUserMobile())
        );
        if(ObjectUtils.isEmpty(user)){
            return R.ERROR(500,"手机号未注册");
        }
        String CodeKey ="phoneCode";
        String PhoneCode = redisTemplate.opsForValue().get(CodeKey);
        if(StringUtils.isEmpty(PhoneCode)){
            return R.ERROR(500,"手机号验证码已过期");
        }
        if(!PhoneCode.equalsIgnoreCase(phoneLoginVo.getPhoneCode())){
            return R.ERROR(500,"手机号验证码错误");
        }
        String token = Jwts.builder().signWith(SignatureAlgorithm.HS256, "123456")
                .claim("userId", user.getUserId()).compact();
        String tokenKey = "token-"+user.getUserId();
        redisTemplate.opsForValue().set(tokenKey,token,20,TimeUnit.MINUTES);
        user.setToken(token);
        return R.OK(user);
    }
}
